package gobang;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.media.CannotRealizeException;
import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.EndOfMediaEvent;
import javax.media.Manager;
import javax.media.NoPlayerException;
import javax.media.Player;
import javax.media.Time;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;


public class Gobang implements ControllerListener{
	public static Player player;
	JPanel panel2 = new JPanel();
	ChessPanel ChessPanel = new ChessPanel();
	JLabel label = new JLabel();
	public Gobang(){
		try{
			aroundblock =new int[2][2][2];
	        intervalblock =new int[2][2][2];
			initAPSIPS();
			Timer timer = new Timer();  
		    timer.schedule(new MyTask(), 1000, 1000);  
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
	class MyTask extends TimerTask {  
		  
	    @Override  
	    public void run() {
	    	if(timeOn){
		       
		        if(withComp){
		        	 remainTimes--;
		        	remainTime = remainTimes+"";
		        	if(remainTimes<=0){
		        		label.setText("0");
		        		try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
		        		JOptionPane.showMessageDialog(null, "黑棋负！");
		        		initQipan();
		        	}
		        }else{
		        	if(blackTurn){
		        		remainTime = remainTimes+"";
		        		remainTimes--;
		        	}else{
		        		remainTime = remainTimes2+"";
		        		 remainTimes2--;
		        	}
		        	if(remainTimes<=0){
		        		label.setText("0");
		        		try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
		        		JOptionPane.showMessageDialog(null, "黑棋负！");
		        		initQipan();
		        	}
		        	if(remainTimes2<=0){
		        		label.setText("0");
		        		try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
		        		JOptionPane.showMessageDialog(null, "白棋负！");
		        		initQipan();
		        	}
		        }
		        label.setText(remainTime);
	    	}
	  
	    }  
	  
	}  
	private static int BLOCK_SIZE = 15;

	private final int BACK_WIDTH = 535;
	private final int BACK_HEIGHT = 536;

	private final int DIVIDE = BACK_WIDTH / BLOCK_SIZE;

	private final int X_OFFSET = 5;
	private final int Y_OFFSET = 6;

	private int[][] block = new int[BLOCK_SIZE][BLOCK_SIZE];
	private int[][] compScor = new int[BLOCK_SIZE][BLOCK_SIZE];

	JFrame frame = new JFrame("五子棋游戏");


	private static int xuanzeX = -1;
	private static int xuanzeY = -1;
	private static int compX = -1;
	private static int compY = -1;

	private static boolean blackWin = false; 
	private static boolean compWin = false; 

	private static int cscore = 0; 
	private static int playerx, playery; 

	BufferedImage table;
	BufferedImage black;
	BufferedImage white;

	BufferedImage selected;
	
	private final int IS_HUO = 1;
	private final int IS_CHONG = 2;
	private static int steps = 0;
	
	private static boolean withComp = true;
	private static boolean blackTurn = true; 

	private ArrayList<ChessXY> listForAI = new ArrayList<ChessXY>();
	private ArrayList<ChessXY> clist = new ArrayList<ChessXY>();
	private ArrayList<ChessXY> cLi = new ArrayList<ChessXY>();
	
	private int [][][]aroundblock; 
	private int [][][]intervalblock;
	
	private boolean playerOn = true;
	private String remainTime = "";
	private int remainTimes = 90;
	private int remainTimes2 = 90;
	private boolean timeOn = false;
	Random rand = new Random();

	public void initQipan() {
		for (int i = 0; i < BLOCK_SIZE; ++i) {
			for (int j = 0; j < BLOCK_SIZE; ++j) {
				block[i][j] = 0;
				compScor[i][j] = 0;
			}
		}
		steps = 0;
		compX = -1;
		compY = -1;
		blackWin = false;
		compWin = false;
		blackTurn = true;
		aroundblock =new int[2][2][2];
        intervalblock =new int[2][2][2];
        initAPSIPS();
        remainTime = "";
        remainTimes = 90;
        remainTimes2 = 90;
        timeOn = false;
        label.setText("");
	}


	public boolean isWin(int f, int x, int y) {
		int i, count = 1;
		boolean up = true, down=true, right=true, left=true, rup=true, lup=true, rdown=true, ldown=true;
		
		/* 左右 */
		for (i = 1; i < 5; ++i) {
			if ((x + i) < BLOCK_SIZE) {
				if (block[x + i][y] == f && right)
					count++;
				else
					right = false;
			}
			if ((x - i) >= 0) {
				if (block[x - i][y] == f && left)
					count++;
				else
					left = false;
			}
		}
		if (count >= 5) {
			return true;
		}
		count = 1;
		/* 上下 */
		for (i = 1; i < 5; ++i) {
			if ((y + i) < BLOCK_SIZE) {
				if (block[x][y + i] == f && down)
					count++;
				else
					down = false;
			}
			if ((y - i) >= 0) {
				if (block[x][y - i] == f && up)
					count++;
				else
					up = false;
			}
		}
		if (count >= 5) {
			return true;
		}
		count = 1;
		/* 左上右下 */
		for (i = 1; i < 5; ++i) {
			if ((x + i) < BLOCK_SIZE && (y + i) < BLOCK_SIZE) {
				if (block[x + i][y + i] == f && rdown)
					count++;
				else
					rdown = false;
			}
			if ((x - i) >= 0 && (y - i) >= 0) {
				if (block[x - i][y - i] == f && lup)
					count++;
				else
					lup = false;
			}
		}
		if (count >= 5) {
			return true;
		}
		count = 1;
		/* 右上左下 */
		for (i = 1; i < 5; ++i) {
			if ((x + i) < BLOCK_SIZE && (y - i) >= 0) {
				if (block[x + i][y - i] == f && rup)
					count++;
				else
					rup = false;
			}
			if ((x - i) >= 0 && (y + i) < BLOCK_SIZE) {
				if (block[x - i][y + i] == f && ldown)
					count++;
				else
					ldown = false;
			}
		}
		if (count >= 5) {
			return true;
		}

		return false;
	}
	
	public boolean isRun(int x, int y) {
		if (block[x][y] == 0) {
			return true;
		}
		return false;
	}
	
	public void AI_GO() {
		cscore = 0;
		for (int i = 0; i < BLOCK_SIZE; ++i) {
			for (int j = 0; j < BLOCK_SIZE; ++j) {
				compScor[i][j] = 0;
			}
		}
		int a = getScore(-1);
		int b = getScore(1);
		if (a >= b) {
			for (int i = listForAI.size(); i >= 0; --i) {
				block[listForAI.get(0).x][listForAI.get(0).y] = -1;
				ChessXY ch = new ChessXY(listForAI.get(0).x, listForAI.get(0).y, getScore(1));
				cLi.add(ch);
				block[listForAI.get(0).x][listForAI.get(0).y] = 0;
			}
			Collections.sort(cLi, new Comparator<ChessXY>() {
				public int compare(ChessXY o1, ChessXY o2) {
					return o1.score - o2.score;
				}
			});
			for (int i = 1; i < cLi.size(); ++i) {
				if (cLi.get(i).score != cLi.get(0).score) {
					cLi.remove(i);
				}
			}
			int n = rand.nextInt(cLi.size());
			playerx = cLi.get(n).x;
			playery = cLi.get(n).y;
			listForAI.clear();
			clist.clear();
			cLi.clear();
		} else {
			boolean flag = true;
			check: for (int i = 0; i < listForAI.size(); ++i) {
				for (int j = 0; j < clist.size(); ++j) {
					if (listForAI.get(i).x == clist.get(j).x && listForAI.get(i).y == clist.get(j).y) {
						playerx = listForAI.get(i).x;
						playery = listForAI.get(i).y;
						listForAI.clear();
						clist.clear();
						flag = false;
						break check;
					}
				}
			}
			if (flag) {
				int n = rand.nextInt(clist.size()); // 电脑根据分值一样的点随机走，防止每次都走相同的步数
				playerx = clist.get(n).x;
				playery = clist.get(n).y;
				listForAI.clear();
				clist.clear();
			}
		}
	}

	public int getScore(int color) {
		cscore = 0;
		for (int i = 0; i < BLOCK_SIZE; ++i) {
			for (int j = 0; j < BLOCK_SIZE; ++j) {
				if (block[i][j] == 0) {
					if (isWin(color, i, j)) // 电脑能赢，故给分最高，因为可以结束，所以不再检测
					{
						cscore = 100000;
						compScor[i][j] = 100000;
					} else if (isWin(-color, i, j)) // 电脑不能赢，玩家能赢，要阻止，所以给12分
					{
						cscore = 80000;
						compScor[i][j] = 80000;
					} else if (isIS_HUOOrIS_CHONG(color, i, j, 4, IS_HUO)) // 电脑玩家都不能赢，电脑能形成活四，给11分
					{
						cscore = (cscore > 40000 ? cscore : 40000);
						compScor[i][j] = 40000;
					} else if (isIS_HUOOrIS_CHONG(color, i, j, 4, IS_CHONG)) // 电脑玩家都不能赢，电脑能形成冲四，给10分
					{
						cscore = (cscore > 10000 ? cscore : 10000);
						compScor[i][j] = 10000;
					} else if (isIS_HUOOrIS_CHONG(-color, i, j, 4, IS_HUO)) // 电脑玩家都不能赢，玩家能形成活四，给9分
					{
						cscore = (cscore > 7000 ? cscore : 7000);
						compScor[i][j] = 7000;
					} else if (isIS_HUOOrIS_CHONG(color, i, j, 3, IS_HUO)) // 电脑玩家都不能赢，电脑能形成活三，给8分
					{
						cscore = (cscore > 4000 ? cscore : 4000);
						compScor[i][j] = 4000;
					} else if (isIS_HUOOrIS_CHONG(-color, i, j, 4, IS_CHONG)) // 电脑玩家都不能赢，玩家能形成冲四，给7分
					{
						cscore = (cscore > 1000 ? cscore : 1000);
						compScor[i][j] = 1000;
					} else if (isIS_HUOOrIS_CHONG(color, i, j, 3, IS_CHONG)) // 电脑玩家都不能赢，电脑能形成冲三，给6分
					{
						cscore = (cscore > 700 ? cscore : 700);
						compScor[i][j] = 700;
					} else if (isIS_HUOOrIS_CHONG(-color, i, j, 3, IS_HUO)) // 电脑玩家都不能赢，玩家能形成冲三，给4分
					{
						cscore = (cscore > 500 ? cscore : 500);
						compScor[i][j] = 500;
					} else if (isIS_HUOOrIS_CHONG(color, i, j, 2, IS_HUO)) // 电脑玩家都不能赢，电脑能形成活二，给5分
					{
						cscore = (cscore > 400 ? cscore : 400);
						compScor[i][j] = 400;
					} else if (isIS_HUOOrIS_CHONG(-color, i, j, 3, IS_CHONG)) // 电脑玩家都不能赢，玩家能形成冲三，给4分
					{
						cscore = (cscore > 200 ? cscore : 200);
						compScor[i][j] = 200;
					} else if (isIS_HUOOrIS_CHONG(-color, i, j, 2, IS_HUO)) // 电脑玩家都不能赢，玩家能形成活二，给3分
					{
						cscore = (cscore > 80 ? cscore : 80);
						compScor[i][j] = 80;
					} else if (isIS_HUOOrIS_CHONG(color, i, j, 2, IS_CHONG)) // 电脑玩家都不能赢，电脑能形成冲二，给2分
					{
						cscore = (cscore > 50 ? cscore : 50);
						compScor[i][j] = 50;
					} else if (isIS_HUOOrIS_CHONG(-color, i, j, 2, IS_CHONG)) // 电脑玩家都不能赢，玩家能形成冲二，给1分
					{
						cscore = (cscore > 10 ? cscore : 10);
						compScor[i][j] = 10;
					} else {
						compScor[i][j] = 0;
					}
				}
			}
		}
		for (int i = 0; i < BLOCK_SIZE; ++i) {
			for (int j = 0; j < BLOCK_SIZE; ++j) {
				if (compScor[i][j] == cscore) {
					ChessXY AI = new ChessXY(i, j, cscore);
					if (color == -1) {
						listForAI.add(AI);
					} else {
						clist.add(AI);
					}
				}
			}
		}
		return cscore;
	}


	private boolean isIS_HUOOrIS_CHONG(int f, int x, int y, int num, int hORc) // 活
	{

		num += 1;
		int i, count = 1;
		boolean terminal1 = false;
		boolean terminal2 = false;
		boolean up, down, right, left, rup, lup, rdown, ldown;
		up = down = right = left = rup = lup = rdown = ldown = true;
		/* 上下 */
		for (i = 1; i < num; ++i) {
			if ((y + i) < BLOCK_SIZE) {
				if (block[x][y + i] == f && down)
					count++;
				else {
					if (block[x][y + i] == 0 && down) {
						terminal1 = true;
					}
					down = false;
				}
			}
			if ((y - i) >= 0) {
				if (block[x][y - i] == f && up)
					count++;
				else {
					if (block[x][y - i] == 0 && up) {
						terminal2 = true;
					}
					up = false;
				}
			}
		}
		if (count == num - 1 && hORc == IS_HUO && terminal1 && terminal2) {
			return true;
		}
		if (count == num - 1 && hORc == IS_CHONG && ((terminal1 && !terminal2) || (!terminal1 && terminal2))) {
			return true;
		}
		count = 1;
		terminal1 = false;
		terminal2 = false;
		/* 左右 */
		for (i = 1; i < num; ++i) {
			if ((x + i) < BLOCK_SIZE) {
				if (block[x + i][y] == f && right)
					count++;
				else {
					if (block[x + i][y] == 0 && right) {
						terminal1 = true;
					}
					right = false;
				}
			}
			if ((x - i) >= 0) {
				if (block[x - i][y] == f && left)
					count++;
				else {
					if (block[x - i][y] == 0 && left) {
						terminal2 = true;
					}
					left = false;
				}
			}
		}
		if (count == num - 1 && hORc == IS_HUO && terminal1 && terminal2) {
			return true;
		}
		if (count == num - 1 && hORc == IS_CHONG && ((terminal1 && !terminal2) || (!terminal1 && terminal2))) {
			return true;
		}
		count = 1;
		terminal1 = false;
		terminal2 = false;
		/* 左上右下 */
		for (i = 1; i < num; ++i) {
			if ((x + i) < BLOCK_SIZE && (y + i) < BLOCK_SIZE) {
				if (block[x + i][y + i] == f && rdown)
					count++;
				else {
					if (block[x + i][y + i] == 0 && rdown) {
						terminal1 = true;
					}
					rdown = false;
				}
			}
			if ((x - i) >= 0 && (y - i) >= 0) {
				if (block[x - i][y - i] == f && lup)
					count++;
				else {
					if (block[x - i][y - i] == 0 && lup) {
						terminal2 = true;
					}
					lup = false;
				}
			}
		}
		if (count == num - 1 && hORc == IS_HUO && terminal1 && terminal2) {
			return true;
		}
		if (count == num - 1 && hORc == IS_CHONG && ((terminal1 && !terminal2) || (!terminal1 && terminal2))) {
			return true;
		}
		count = 1;
		terminal1 = false;
		terminal2 = false;
		/* 右上左下 */
		for (i = 1; i < num; ++i) {
			if ((x + i) < BLOCK_SIZE && (y - i) >= 0) {
				if (block[x + i][y - i] == f && rup)
					count++;
				else {
					if (block[x + i][y - i] == 0 && rup) {
						terminal1 = true;
					}
					rup = false;
				}
			}
			if ((x - i) >= 0 && (y + i) < BLOCK_SIZE) {
				if (block[x - i][y + i] == f && ldown)
					count++;
				else {
					if (block[x - i][y + i] == 0 && ldown) {
						terminal2 = true;
					}
					ldown = false;
				}
			}
		}
		if (count == num - 1 && hORc == IS_HUO && terminal1 && terminal2) {
			return true;
		}
		if (count == num - 1 && hORc == IS_CHONG && ((terminal1 && !terminal2) || (!terminal1 && terminal2))) {
			return true;
		}

		return false;
	}

	public void init() throws Exception {
		table = ImageIO.read(new File("image/block.jpg"));
		black = ImageIO.read(new File("image/black.gif"));
		white = ImageIO.read(new File("image/white.gif"));
		selected = ImageIO.read(new File("image/selected.gif"));

		for (int i = 0; i < BLOCK_SIZE; ++i) {
			for (int j = 0; j < BLOCK_SIZE; ++j) {
				block[i][j] = 0;
				compScor[i][j] = 0;
			}
		}
		ChessPanel.setPreferredSize(new Dimension(BACK_WIDTH, BACK_HEIGHT));
		ChessPanel.setSize(BACK_WIDTH, BACK_WIDTH);
		ChessPanel.setLocation(0, 0);
		ChessPanel.addMouseListener(new MouseAdapterWithComp());
		ChessPanel.addMouseMotionListener(new MouseMotionAdapter() {
			public void mouseMoved(MouseEvent e) {
				xuanzeX = (e.getX() - X_OFFSET) / DIVIDE;
				xuanzeY = (e.getY() - Y_OFFSET) / DIVIDE;
				ChessPanel.repaint();
			}
		});
		
		JMenuBar bar = new JMenuBar();
		JMenu menu1 = new JMenu("模式选择");
		JMenuItem item1 = new JMenuItem("人机对战");
		item1.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				withComp = true;
				initQipan();
			}
			
		});
		JMenuItem item2 = new JMenuItem("双人对战");
		item2.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				withComp = false;
				initQipan();
			}
			
		});
		JMenuItem item3 = new JMenuItem("退出游戏");
		item3.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				frame.dispose();
			}
		});
		menu1.add(item1);
		menu1.add(item2);
		menu1.add(item3);
		bar.add(menu1);
		JMenu menu2 = new JMenu("难度设置");
		JMenuItem item4 = new JMenuItem("简单");
		menu2.add(item4);
		JMenuItem item7 = new JMenuItem("中等");
		menu2.add(item7);
		JMenuItem item8 = new JMenuItem("困难");
		menu2.add(item8);
		bar.add(menu2);
		
		JMenu menu4 = new JMenu("背景音乐");
		JMenuItem item9 = new JMenuItem("开");
		item9.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				player.getGainControl().setMute(false);
			}
		});
		menu4.add(item9);
		JMenuItem item10 = new JMenuItem("关");
		menu4.add(item10);
		item10.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				player.getGainControl().setMute(true);
			}
		});
		bar.add(menu4);
		
		JMenu menu5 = new JMenu("计时模式");
		JMenuItem item11 = new JMenuItem("开");
		item11.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				remainTime = "90";
				timeOn = true;
				remainTimes = 90;
				remainTimes2 = 90;
			}
		});
		menu5.add(item11);
		JMenuItem item12 = new JMenuItem("关");
		menu5.add(item12);
		item12.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				remainTime = "";
				timeOn = false;
				remainTimes = 90;
				remainTimes2 = 90;
			}
		});
		bar.add(menu5);
		
		JMenu menu3 = new JMenu("游戏帮助");
		JMenuItem item5 = new JMenuItem("游戏说明");
		item5.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(null, "这里是游戏说明，根据你的论文自己填写一下吧！");
			}
		});
		JMenuItem item6 = new JMenuItem("关于作者");
		item6.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(null, "李雪健");
				
			}
		});
		menu3.add(item5);
		menu3.add(item6);
		bar.add(menu3);
		frame.setLayout(null);
		panel2.setBounds(0, 550, 540, 40);
		panel2.setLayout(null);
		
		label.setBounds(230, 0, 100, 30);
		label.setForeground(Color.red);
		label.setFont(new Font("Times New Roman",Font.BOLD,30));
		panel2.add(label);
		frame.setJMenuBar(bar);
		frame.setLocation(300, 50);
		frame.setSize(540, 630);
		frame.add(ChessPanel);
		frame.add(panel2);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setResizable(false);
		frame.setVisible(true);
		this.playmusic();
	}
	public static void main(String[] args) throws Exception {
		Gobang game = new Gobang();
		game.init();
	}
	class MouseAdapterWithComp extends MouseAdapter{

		public void mouseClicked(MouseEvent e) {
			if(withComp){
				if(remainTimes<=20){
					remainTimes = 20;
				}
				int xPos = (int) ((e.getX() - X_OFFSET) / DIVIDE);
				int yPos = (int) ((e.getY() - Y_OFFSET) / DIVIDE);
				if (isRun(xPos, yPos)) {
					boolean jinshou = isIled(xPos, yPos, 1);
					if(jinshou){
						JOptionPane.showMessageDialog(null, "黑禁手负", "结束", JOptionPane.ERROR_MESSAGE);
						initQipan();
						blackTurn = true;
						return;
					}
					blackWin = isWin(1, xPos, yPos);
					block[xPos][yPos] = 1;
					steps++;
					ChessPanel.repaint();
					if (steps == (BLOCK_SIZE * BLOCK_SIZE)) {
						JOptionPane.showMessageDialog(null, "平手！", "结束", JOptionPane.ERROR_MESSAGE);
						initQipan();
					} else {
						
						AI_GO(); 
						steps++;
						ChessPanel.repaint();
						compWin = isWin(-1, playerx, playery);
						block[playerx][playery] = -1;
						compX = playerx;
						compY = playery;
					}
				}
				if (blackWin) {
					JOptionPane.showMessageDialog(null, "黑棋赢！", "结束", JOptionPane.ERROR_MESSAGE);
					initQipan();
				} else if (compWin) {
					JOptionPane.showMessageDialog(null, "白棋赢！", "结束", JOptionPane.ERROR_MESSAGE);
					initQipan();
				}
			}else{
				int xPos = (int) ((e.getX() - X_OFFSET) / DIVIDE);
				int yPos = (int) ((e.getY() - Y_OFFSET) / DIVIDE);
				if (isRun(xPos, yPos)) {
					if(blackTurn){
						if(remainTimes<=20){
							remainTimes = 20;
						}
						boolean jinshou = isIled(xPos, yPos, 1);
						if(jinshou){
							JOptionPane.showMessageDialog(null, "黑禁手负", "结束", JOptionPane.ERROR_MESSAGE);
							initQipan();
							blackTurn = true;
							return;
						}
						blackWin = isWin(1, xPos, yPos);
						block[xPos][yPos] = 1;
						steps++;
						ChessPanel.repaint();
						blackTurn = false;
					}else{
						if(remainTimes2<=20){
							remainTimes2 = 20;
						}
						compWin = isWin(-1, xPos, yPos);
						block[xPos][yPos] = -1;
						steps++;
						compX = xPos;
						compY = yPos;
						ChessPanel.repaint();
						blackTurn = true;
					}
					if (steps == (BLOCK_SIZE * BLOCK_SIZE)) {
						JOptionPane.showMessageDialog(null, "平手！", "结束", JOptionPane.ERROR_MESSAGE);
						initQipan();
					}
				}
				if (blackWin) {
					JOptionPane.showMessageDialog(null, "黑棋赢！", "结束", JOptionPane.ERROR_MESSAGE);
					initQipan();
				} else if (compWin) {
					JOptionPane.showMessageDialog(null, "白棋赢！", "结束", JOptionPane.ERROR_MESSAGE);
					initQipan();
				}
			}
		}

		public void mouseExited(MouseEvent e) {
			xuanzeX = -1;
			xuanzeY = -1;
			ChessPanel.repaint();
		}
	
	}
	private void initAPSIPS() // 初始化 aroundblock
    {
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
                for(int k=0;k<2;k++)
                {
                    aroundblock[i][j][k]=0;
                    intervalblock[i][j][k]=0;
                }
    }
	private boolean doJudge(int x, int y, int tag, int xtag,int ytag, int waytag)
    {
        int maxcount; //计算最大循环次数用的
        if(ytag==0)   //纵向时用 x
        {
            if(waytag==0) maxcount=x; //上
            else maxcount=BLOCK_SIZE-1-x; //下
        }
        else   //其他用 y 
        {
            if(waytag==0) maxcount=y; //左上、左、左下
            else maxcount=BLOCK_SIZE-1-y; //右下、右、右上
        }
        
        if( ((xtag==1&&(x+xtag)<BLOCK_SIZE) || (xtag==0) || (xtag==-1&&(x+xtag)>=0)) //纵向不越界 
            &&
            ((ytag==1&&(y+ytag)<BLOCK_SIZE) || (ytag==0) || (ytag==-1&&(y+ytag)>=0)) //横向不越界
            &&
           block[x+xtag][y+ytag]==0 //相邻先是空格
          )
        {
            aroundblock[0][0][waytag]++;
            for(int i=2;i<=maxcount;i++)
            {
                if(aroundblock[1][1][waytag]==0&&
                   ((xtag==1&&(x+i)<BLOCK_SIZE) || (xtag==0) || (xtag==-1&&(x-i)>=0)) //纵向不越界 
                   &&
                   ((ytag==1&&(y+i)<BLOCK_SIZE) || (ytag==0) || (ytag==-1&&(y-i)>=0)) //横向不越界
                   &&
                   block[x+xtag*i][y+ytag*i]==0  //空格
                  )
                    aroundblock[0][0][waytag]++;    
                
                else if(  intervalblock[0][0][waytag]==0&&
                           ((xtag==1&&(x+i)<BLOCK_SIZE) || (xtag==0) || (xtag==-1&&(x-i)>=0)) //纵向不越界 
                           &&
                           ((ytag==1&&(y+i)<BLOCK_SIZE) || (ytag==0) || (ytag==-1&&(y-i)>=0)) //横向不越界
                           &&
                           block[x+xtag*i][y+ytag*i]==tag //相同子
                        )
                    aroundblock[1][1][waytag]++;
                
                else if(aroundblock[1][1][waytag]!=0
                         &&
                         intervalblock[1][1][waytag]==0
                         &&
                         ((xtag==1&&(x+i)<BLOCK_SIZE) || (xtag==0) || (xtag==-1&&(x-i)>=0)) //纵向不越界 
                         &&
                         ((ytag==1&&(y+i)<BLOCK_SIZE) || (ytag==0) || (ytag==-1&&(y-i)>=0)) //横向不越界
                         &&
                         block[x+xtag*i][y+ytag*i]==0 //间隔空格
                        )
                    intervalblock[0][0][waytag]++;
                
                else if(intervalblock[0][0][waytag]!=0&&
                         ((xtag==1&&(x+i)<BLOCK_SIZE) || (xtag==0) || (xtag==-1&&(x-i)>=0)) //纵向不越界 
                         &&
                         ((ytag==1&&(y+i)<BLOCK_SIZE) || (ytag==0) || (ytag==-1&&(y-i)>=0)) //横向不越界
                         &&
                         block[x+xtag*i][y+ytag*i]==tag //间隔相同子
                         )
                    intervalblock[1][1][waytag]++;
                else 
                    break;
            }
        }
        
        else if( ((xtag==1&&(x+xtag)<BLOCK_SIZE) || (xtag==0) || (xtag==-1&&(x+xtag)>=0)) //纵向不越界 
                  &&
                  ((ytag==1&&(y+ytag)<BLOCK_SIZE) || (ytag==0) || (ytag==-1&&(y+ytag)>=0)) //横向不越界
                  &&
                  block[x+xtag][y+ytag]==tag //相邻先是相同子
                ) 
            {
                aroundblock[0][1][waytag]++;
                for(int i=2;i<=maxcount;i++)
                {
                    if(aroundblock[1][0][waytag]==0&&
                       ((xtag==1&&(x+i)<BLOCK_SIZE) || (xtag==0) || (xtag==-1&&(x-i)>=0)) //纵向不越界 
                       &&
                       ((ytag==1&&(y+i)<BLOCK_SIZE) || (ytag==0) || (ytag==-1&&(y-i)>=0)) //横向不越界
                       &&
                       block[x+xtag*i][y+ytag*i]==tag //相同子
                      )
                        aroundblock[0][1][waytag]++;
                    
                    else if(  intervalblock[0][1][waytag]==0&&
                             ((xtag==1&&(x+i)<BLOCK_SIZE) || (xtag==0) || (xtag==-1&&(x-i)>=0)) //纵向不越界 
                             &&
                             ((ytag==1&&(y+i)<BLOCK_SIZE) || (ytag==0) || (ytag==-1&&(y-i)>=0)) //横向不越界
                             &&
                             block[x+xtag*i][y+ytag*i]==0 //空格
                            )
                        aroundblock[1][0][waytag]++;
                    
                    else if( aroundblock[1][0][waytag]!=0
                             &&
                             intervalblock[1][0][waytag]==0
                             &&
                             ((xtag==1&&(x+i)<BLOCK_SIZE) || (xtag==0) || (xtag==-1&&(x-i)>=0)) //纵向不越界 
                             &&
                             ((ytag==1&&(y+i)<BLOCK_SIZE) || (ytag==0) || (ytag==-1&&(y-i)>=0)) //横向不越界
                             &&
                             block[x+xtag*i][y+ytag*i]==tag //间隔相同子
                             )
                        intervalblock[0][1][waytag]++;                    
                    
                    else if(intervalblock[0][1][waytag]!=0&&
                             ((xtag==1&&(x+i)<BLOCK_SIZE) || (xtag==0) || (xtag==-1&&(x-i)>=0)) //纵向不越界 
                             &&
                             ((ytag==1&&(y+i)<BLOCK_SIZE) || (ytag==0) || (ytag==-1&&(y-i)>=0)) //横向不越界
                             &&
                             block[x+xtag*i][y+ytag*i]==0 //间隔空格
                             )
                        intervalblock[1][0][waytag]++;
                    
                    else 
                        break;
                }
            }
        else return false;  //相邻为不同子，直接返回
        
        return true; //最后返回true
    }
	private boolean isConStraightThree()//判断是否为连活三
    {
    //有3种情况，分别列出3种情况，看其阳线或阴线周围情况是否符合
        //先来是判断是否为连活三，情况都是以左、中、右或上、中、下来列
        if(aroundblock[0][1][1]==2
            &&
            ((aroundblock[0][0][0]>=1&&aroundblock[1][0][1]>=2)
            ||(aroundblock[0][0][0]>=2&&aroundblock[1][0][1]>=1))
           )
            return true;
        else if(aroundblock[0][1][0]==1&&aroundblock[0][1][1]==1
                 &&
                 ((aroundblock[1][0][0]>=1&&aroundblock[1][0][1]>=2)
                 ||(aroundblock[1][0][0]>=2&&aroundblock[1][0][1]>=1))
                )
            return true;
        else if(aroundblock[0][1][0]==2
                 &&
                 ((aroundblock[1][0][0]>=1&&aroundblock[0][0][1]>=2)
                 ||(aroundblock[1][0][0]>=2&&aroundblock[0][0][1]>=1))
                )
            return true;
        
        return false;  //以上3种情况都不是，非连活三
    }
    
    private boolean isJumpStraightThree() //判断是否为跳活三
    {
   //有两种情况，左2右1、左1右2 分别列出3种情况，看其阳线或阴线周围情况是否符合
        //先左2右1  判断子顺序 左、中、右
        if(aroundblock[0][1][1]==1&&aroundblock[1][0][1]==1
            &&intervalblock[0][1][1]==1
            &&
            ((aroundblock[0][0][0]>=1&&intervalblock[1][0][1]>=2)
            ||(aroundblock[0][0][0]>=2&&intervalblock[1][0][1]>=1))
           )
            return true;
        
        else if(aroundblock[0][1][0]==1&&
                aroundblock[0][0][1]==1&&aroundblock[1][1][1]==1
                &&
                ((aroundblock[1][0][0]>=1&&intervalblock[0][0][1]>=2)
               ||(aroundblock[1][0][0]>=2&&intervalblock[0][0][1]>=1))
                )
            return true;
        
        else if(aroundblock[0][0][0]==1
                &&aroundblock[1][1][0]==2
                &&
                ((intervalblock[0][0][0]>=1&&aroundblock[0][0][1]>=2)
                ||(intervalblock[0][0][0]>=2&&aroundblock[0][0][1]>=1))
                )
            return true;
        
        //接下来 左1右2   判断子顺序 左、中、右
        if(aroundblock[0][0][1]==1&&aroundblock[1][1][1]==2
           &&
           ((aroundblock[0][0][0]>=1&&intervalblock[0][0][1]>=2)
           ||(aroundblock[0][0][0]>=2&&intervalblock[0][0][1]>=1))
           )
            return true;
        
        else if(aroundblock[0][0][0]==1&&
                 aroundblock[1][1][0]==1&&aroundblock[0][1][1]==1
                 &&
                 ((intervalblock[0][0][0]>=1&&aroundblock[1][0][1]>=2)
                 ||(intervalblock[0][0][0]>=2&&aroundblock[1][0][1]>=1))
                )
            return true;
        
        else if(aroundblock[0][1][0]==1&&aroundblock[1][0][0]==1
                 &&intervalblock[0][1][0]==1
                 &&
                 ((aroundblock[0][0][1]>=1&&intervalblock[1][0][0]>=2)
                 ||(aroundblock[0][0][1]>=2&&intervalblock[1][0][0]>=1))
                  )
                return true;
        
        return false; //以上6种情况都不是，非跳活三
    }
    
    private boolean isContinuousFour()   //是否为冲四
    {
        //这里判断是否为冲四，依旧是列举每种情况，看是否是，4类，每类4中情况
        
        //左1右3   左1、右3、右2、右1
        if(aroundblock[0][0][1]==1&&aroundblock[1][1][1]==3&&
           aroundblock[0][1][0]==0)
            return true;
        else if(aroundblock[0][0][0]==1&&aroundblock[1][1][0]==1
            &&intervalblock[0][1][0]==0&&aroundblock[0][1][1]==2)
            return true;
        else if(aroundblock[0][1][0]==1&&aroundblock[1][0][0]==1
            &&intervalblock[0][1][0]==1&&aroundblock[0][1][1]==1)        
            return true;
        else if(aroundblock[0][1][0]==2&&aroundblock[1][0][0]==1
            &&intervalblock[0][1][0]==1&&aroundblock[0][1][1]==0)
            return true;
        
        //左2右2   左1、左2、右2、右1
        if(aroundblock[0][1][0]==0&&aroundblock[0][1][1]==1&&
           aroundblock[1][0][1]==1&&intervalblock[0][1][1]==2)
            return true;
        else if(aroundblock[0][1][0]==1&&
            aroundblock[0][0][1]==1 &&aroundblock[1][1][1]==2)
            return true;
        else if(aroundblock[0][0][0]==1&&aroundblock[1][1][0]==2
            &&aroundblock[0][1][1]==1)
            return true;
        else if(aroundblock[0][1][0]==1&&aroundblock[1][0][0]==1
            &&intervalblock[0][1][0]==2&&aroundblock[0][1][1]==0)
            return true;
        
        //左3右1   左1、左2、左3、右1
        if(aroundblock[0][1][0]==0&&aroundblock[0][1][1]==2&&
           aroundblock[1][0][1]==1&&intervalblock[0][1][1]==1)
            return true;
        else if(aroundblock[0][1][0]==1&&aroundblock[0][1][1]==1
            &&aroundblock[1][0][1]==1&&intervalblock[0][1][1]==1)
            return true;
        else if(aroundblock[0][1][0]==2&&
            aroundblock[0][0][1]==1&&aroundblock[1][1][1]==1)
            return true;
        else if(aroundblock[0][0][0]==1&&aroundblock[1][1][0]==3
            &&aroundblock[0][1][1]==0)
            return true;
        
        //4个连一起   左、中间2个、右
        if(
           aroundblock[0][1][1]==3&&( (aroundblock[0][0][0]==0
            &&aroundblock[0][1][0]==0&&aroundblock[1][0][1]>=1)
           ||(aroundblock[0][0][0]>=1&&aroundblock[1][0][1]==0) )
          )
            return true;
        
        else if(
           ( (aroundblock[0][1][0]==1&&aroundblock[0][1][1]==2)
           ||(aroundblock[0][1][0]==2&&aroundblock[0][1][1]==1) )
               &&
           ( (aroundblock[1][0][0]==0&&aroundblock[1][0][1]>=1)
           ||(aroundblock[1][0][0]>=1&&aroundblock[1][0][1]==0) )    
                )
            return true;
        
        else if(
           aroundblock[0][1][0]==3&&( (aroundblock[0][0][1]==0
            &&aroundblock[0][1][1]==0&&aroundblock[1][0][0]>=1)
           ||(aroundblock[0][0][1]>=1&&aroundblock[1][0][0]==0) )
                  )
            return true;
            
        return false; //以上都不是 返回false
    }
    
    private boolean isStraightFour() //是否为活四
    {
        //判断是否为活四，4种情况，列出  左、中间2个、右
        if( aroundblock[0][1][1]==3&&
        ( (aroundblock[0][0][0]>=1&&aroundblock[1][0][1]>=2)
        ||(aroundblock[0][0][0]>=2&&aroundblock[1][0][1]>=1) )
           )
            return true;
        else if(
           ( (aroundblock[0][1][0]==1&&aroundblock[0][1][1]==2)
           ||(aroundblock[0][1][0]==2&&aroundblock[0][1][1]==1) )   
             &&
           ( (aroundblock[1][0][0]>=1&&aroundblock[1][0][1]>=2)
           ||(aroundblock[1][0][0]>=2&&aroundblock[1][0][1]>=1) )             
                )
             return true;
        else if( aroundblock[0][1][0]==3&&
           ( (aroundblock[1][0][0]>=1&&aroundblock[0][0][1]>=2)
           ||(aroundblock[1][0][0]>=2&&aroundblock[0][0][1]>=1) )
                )
            return true;
        
        return false;  //以上情况都不是，返回false
    }
	public boolean isIled(int x, int y, int tag)//判断是否为禁手
    {
        //约定：X为横轴，XY为45°斜轴，Y为纵轴，YX为135°斜轴
       //记录该行三的个数，该行四的个数
        int numThreeX=0,numFourX=0; 
        int numThreeXY=0,numFourXY=0;
        int numThreeY=0,numFourY=0;
        int numThreeYX=0,numFourYX=0;
         
        initAPSIPS();   //初始化                          
        doJudge(x, y, tag, 0, -1, 0);//横向  左
        doJudge(x, y, tag, 0, 1, 1); //右
        if(isConStraightThree()||isJumpStraightThree())  //是否有活三
            numThreeX++;
        if(isContinuousFour()||isStraightFour())  //是否有冲四或活四
            numFourX++;
        
        initAPSIPS();   //初始化                          
        doJudge(x, y, tag, 1, -1, 0);//升斜向  左下
        doJudge(x, y, tag, -1, 1, 1); //右上
        if(isConStraightThree()||isJumpStraightThree())  //是否有活三
            numThreeXY++;
        if(isContinuousFour()||isStraightFour())  //是否有冲四或活四
            numFourXY++;
        
        initAPSIPS();   //初始化                          
        doJudge(x, y, tag, 1, 0, 0);//纵向  上
        doJudge(x, y, tag, -1, 0, 1); //下
        if(isConStraightThree()||isJumpStraightThree())  //是否有活三
            numThreeY++;
        if(isContinuousFour()||isStraightFour())  //是否有冲四或活四
            numFourY++;            
        
        initAPSIPS();   //初始化                          
        doJudge(x, y, tag, -1, -1, 0);//降斜向  左上
        doJudge(x, y, tag, 1, 1, 1); //右下
        if(isConStraightThree()||isJumpStraightThree())  //是否有活三
            numThreeYX++;
        if(isContinuousFour()||isStraightFour())  //是否有冲四或活四
            numFourYX++;
        
        if( (numThreeX+numThreeXY+numThreeY+numThreeYX)>=2 //三三
         ||  (numFourX+numFourXY+numFourY+numFourYX)>=2 )  //四四 类
            return true;                 //包含了四四三、四三三类
        if(checkIsLong(x,y,tag)){
        	return true;
        }
        return false; //以上不符合，返回false
    }
	public boolean checkIsLong(int x, int y, int tag)//是否长连
    {
        int  sum=0; // 连子总数
        for(int i=1;i<=4;i++) //横向 左
        {
            if((y-i)>=0&&block[x][y-i]==tag)
                sum++;
            else break;
        }
        for(int i=1;i<=4;i++) //横向 右
        {
            if((y+i)<BLOCK_SIZE&&block[x][y+i]==tag)
                sum++;
            else break;
        }
        if(sum>4) //长连
            return true;
        
        sum=0; //还原
        for(int i=1;i<=4;i++) //纵向 上
        {
            if((x-i)>=0&&block[x-i][y]==tag)
                sum++;
            else break;
        }
        for(int i=1;i<=4;i++) //纵向 下
        {
            if((x+i)<BLOCK_SIZE&&block[x+i][y]==tag)
                sum++;
            else break;
        }
        
        if(sum>4) //长连
        	return true;
        sum=0; //还原
        for(int i=1;i<=4;i++)  //斜向 右上
        {
            if((x-i)>=0&&(y+i)<BLOCK_SIZE&&block[x-i][y+i]==tag)
                sum++;
            else break;
        }
        for(int i=1;i<=4;i++)  //斜向 左下
        {
            if((x+i)<BLOCK_SIZE&&(y-i)>=0&&block[x+i][y-i]==tag)
                sum++;
            else break;
        }
        
        if(sum>4)  //长连
            return true;
        
        sum=0; //还原
        for(int i=1;i<=4;i++)  //斜向 左上
        {
            if((x-i)>=0&&(y-i)>=0&&block[x-i][y-i]==tag)
                sum++;
            else break;
        }
        for(int i=1;i<=4;i++)  //斜向 右下
        {
            if((x+i)<BLOCK_SIZE&&(y+i)<BLOCK_SIZE&&block[x+i][y+i]==tag)
                sum++;
            else break;
        }
      
        if(sum>4) //长连
        	return true;
        return false;  //上面均没成功，最后返回false
    }
	class ChessPanel extends JPanel {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public void paint(Graphics g) {
			g.drawImage(table, 0, 0, null);
			if (xuanzeX >= 0 && xuanzeY >= 0) {
				g.drawImage(selected, xuanzeX * DIVIDE + X_OFFSET, xuanzeY * DIVIDE + Y_OFFSET, null);
			}
			if (compX >= 0 && compY >= 0) {
				g.drawImage(selected, compX * DIVIDE + X_OFFSET, compY * DIVIDE + Y_OFFSET, null);
			}
			for (int i = 0; i < BLOCK_SIZE; ++i) {
				for (int j = 0; j < BLOCK_SIZE; ++j) {
					if (block[i][j] == 1) {
						g.drawImage(black, i * DIVIDE + X_OFFSET, j * DIVIDE + Y_OFFSET, null);
					}
					if (block[i][j] == -1) {
						g.drawImage(white, i * DIVIDE + X_OFFSET, j * DIVIDE + Y_OFFSET, null);
					}
				}
			}
		}
	}
	public void playmusic() throws NoPlayerException, CannotRealizeException, IOException{
		
		URL cb=Gobang.class.getResource("4296.wav");
		
		
		player = Manager.createRealizedPlayer(cb);
		if(!playerOn){
			player.getGainControl().setMute(true);
		}else{
			player.getGainControl().setMute(false);
		}
		player.addControllerListener(this);
		player.start();
		
		
	}
	public void controllerUpdate(ControllerEvent e) {
		// TODO Auto-generated method stub
		 if (e instanceof EndOfMediaEvent)
         {
             player.setMediaTime(new Time(0));
             
             player.start();
            
         }
	}
}


